package com.example.sup.service.impl;


import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.sup.constants.EquipmentStateEnum;
import com.example.sup.constants.EventStateEnum;
import com.example.sup.controller.request.DistrictPrisonRequest;
import com.example.sup.controller.request.PrisonQueryRequest;
import com.example.sup.controller.request.QueryTemperRequest;
import com.example.sup.entity.*;
import com.example.sup.exception.CommonQueryException;
import com.example.sup.service.*;
import com.example.sup.mapper.PrisonMapper;
import com.example.sup.utils.RedisUtils;
import com.example.sup.vo.CompletePrisonVO;
import com.example.sup.vo.PrisonDistrictVO;
import com.example.sup.vo.PrisonQueryPageVO;
import com.example.sup.vo.PrisonTemperatureVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.example.sup.constants.PrisonStatusEnum.*;
import static com.example.sup.constants.UserInfoRoleEnum.ADMIN;

/**
* @author mac
* @description 针对表【prison(监室表)】的数据库操作Service实现
* @createDate 2024-07-19 10:05:17
*/
@Service
@Slf4j
public class PrisonServiceImpl extends ServiceImpl<PrisonMapper, Prison>
    implements PrisonService{



    @Resource
    private PrisonService prisonService;

    @Resource
    private EquipmentInfoService equipmentInfoService;

    @Resource
    private PrisonTypeService prisonTypeService;



    @Resource
    private JackInfoService jackInfoService;
    @Resource
    private EventInfoService eventInfoService;


    @Resource
    private RedisUtils redisUtil;
    public List<CompletePrisonVO> queryCompletePrisonList(UserInfo userInfo) {
        List<CompletePrisonVO> completePrisonVOList = new ArrayList<>();
        //TODO 0、查询当前登录用户的id
        //TODO 1.prison表--查询登录用户所关联的监视列表
        Wrapper prisonQueryWrapper = new QueryWrapper<Prison>().lambda()
                .eq(Prison::getUserInfoId,userInfo.getUserId());
        List<Prison> prisonList = userInfo.getRole().equals(ADMIN.getCode())? this.list():this.list(prisonQueryWrapper);
        //entity--->vo
        prisonList.forEach(prison -> {
            CompletePrisonVO completePrisonVO = new CompletePrisonVO();
            //属性拷贝：将prison实体类对象的属性拷贝到CompletePrisonVO对象的属性上
            /**
             * 对象属性拷贝方案：
             * 1、BeanUtils（spring、apache、hutools)工具类，底层是使用的反射技术，反射技术在数据量大的时候，是有性能问题
             * 2、cglibcopier 字节码拼接技术，性能会更好
             *      1)原型设计模式
             * 3、mapstruct Mapstruct正是在java文件到class这一步帮我们实现了转换方法，即做了预处理，提前编译好文件。
             */
            prison.clone(completePrisonVO);
            completePrisonVOList.add(completePrisonVO);
        });
        //TODO 2.event_info表----不需要
        completePrisonVOList.forEach(completePrisonVO -> {
            Wrapper eventInfoQueryWrapper = new QueryWrapper<EventInfo>()
                    .eq("prison_id", completePrisonVO.getPrisonId());
            List<EventInfo> eventInfoList = eventInfoService.list(eventInfoQueryWrapper);
            if(eventInfoList!=null&&eventInfoList.size()>0){
                completePrisonVO.setPrisonState(WARNING.getCode());
            }
        });
        //3.equipment_info表 ----不需要

        //4.prison_type ---不需要
        //5.vprion_jack视图---不需要
        //6.jack_info表---不需要
        return completePrisonVOList;
    }

    @Override
    public PrisonTemperatureVO queryTemper(UserInfo userInfo, QueryTemperRequest queryTemperRequest) {
        //1.获取指定用户绑定的监室
        //2.权限校验,校验该用户是否有权限查看该监室的温度和湿度信息
        if(!userInfo.getRole().equals(ADMIN.getCode())){//非管理员,角色1为管理员，2位普通用户
            Wrapper prisonQueryWrapper = new QueryWrapper<Prison>().lambda()
                    .eq(Prison::getUserInfoId,userInfo.getUserId());
            List<Prison> prisonList = this.list(prisonQueryWrapper);

            if(prisonList==null||prisonList.size()<=0){
                throw new CommonQueryException("目前您没有负责的监室...，请先联系管理员");
            }
            List<Prison> authPrisonList = prisonList.stream().filter(prison -> {
                return prison.getPrisonId().equals(queryTemperRequest.getPrisonId());
            }).collect(Collectors.toList());
            if(authPrisonList==null||authPrisonList.size()<=0){
                throw new CommonQueryException("无权查看该监室信息，请先联系管理员");
            }
        }
        //3.查询指定监室的温度和湿度
        Prison prison = baseMapper.queryTemperAndHumidity(queryTemperRequest.getPrisonId());
        log.info("查询到的监室信息：{}",prison);

        //4.entity转vo
        PrisonTemperatureVO prisonTemperatureVO = new PrisonTemperatureVO();
        prison.getHumidity().clone(prisonTemperatureVO);
        prison.getTemperature().clone(prisonTemperatureVO);
        return prisonTemperatureVO;
    }
    @Override
    public List<PrisonDistrictVO> queryPrisonByDistrictId(UserInfo userInfo, DistrictPrisonRequest districtPrisonRequest) {
        //TODO 0、查询当前登录用户的id
        log.info("当前登录用户信息：{}",userInfo);
        //3.查询监室信息
        List<Prison> prisonList = this.baseMapper.queryPrisonByDistrictId(districtPrisonRequest.getPrisonDistrictId());
        //2.权限校验,校验该用户是否有权限查看该监室的温度和湿度信息
        if(!userInfo.getRole().equals(ADMIN.getCode())) {//非管理员,角色1为管理员，2位普通用户
            prisonList =  prisonList.stream().filter(prison ->
                    prison.getUserInfoId().equals(userInfo.getUserId())
            ).collect(Collectors.toList());
        }
        //4.entity转Vo
        //TODO 优化：集合能确定大小，在创建时就要指定大小，避免扩容
        List<PrisonDistrictVO> prisonDistrictVOList = new ArrayList<>(prisonList.size());
        prisonDistrictVOList = prisonList.stream().map(prison->{

            PrisonDistrictVO prisonDistrictVO = prison.clone(PrisonDistrictVO.class);
            prisonDistrictVO.setPrisonState(ONLINE.getCode());
            //判断离线
            if(prison.getEquipmentInfo().getState().equals(EquipmentStateEnum.OFFLINE.getCode())){
                //设备状态  1：在线 0：离线
                prisonDistrictVO.setPrisonState(OFFLINE.getCode());
            }
            //判断告警
            if(prison.getEventInfoList()!=null&&prison.getEventInfoList().size()>0){
                log.debug("告警信息：{}",prison.getEventInfoList());
                if(prison.getEventInfoList().stream().anyMatch(eventInfo -> {
                    if(eventInfo.getState()!=null){
                        return eventInfo.getState().equals(EventStateEnum.UNFIXED.getCode());
                    }
                    return false;
                })){
                    prisonDistrictVO.setPrisonState(WARNING.getCode());
                }
            }
            return prisonDistrictVO;
        }).collect(Collectors.toList());
        return prisonDistrictVOList;
    }




    /**
     * 根据请求参数查询监狱信息并返回分页结果。
     *
     * @param request 请求参数
     * @return 分页查询结果
     */
    public Page<PrisonQueryPageVO> queryPrisonInfo(PrisonQueryRequest request) {
        // 1. 根据请求参数查询监狱信息
        List<Prison> prisonList = fetchPrisonList(request);

        // 2. 处理监狱信息
        List<PrisonQueryPageVO> resultList = processPrisonList(prisonList);

        // 3. 构建分页结果并返回
        Page<PrisonQueryPageVO> page = buildPageResult(request, resultList);
        return page;
    }

    /**
     * 根据请求参数获取监狱列表。
     *
     * @param request 请求参数
     * @return 监狱列表
     */
    private List<Prison> fetchPrisonList(PrisonQueryRequest request) {
        String prisonName = request.getPrisonName();
        Integer prisonTypeId = request.getPrisonTypeId();
        QueryWrapper<Prison> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(prisonName != null, "prison_name", prisonName);
        queryWrapper.eq(prisonTypeId != null, "prison_type_id", prisonTypeId);
        return prisonService.list(queryWrapper);
    }

    /**
     * 处理监狱列表数据。
     *
     * @param prisonList 监狱列表
     * @return 处理后的监狱信息列表
     */
    private List<PrisonQueryPageVO> processPrisonList(List<Prison> prisonList) {
        List<PrisonQueryPageVO> resultList = new ArrayList<>();
        for (Prison prison : prisonList) {
            PrisonQueryPageVO vo = processPrisonData(prison);
            resultList.add(vo);
        }
        return resultList;
    }

    /**
     * 处理单个监狱的信息。
     *
     * @param prison 监狱信息
     * @return 处理后的监狱信息
     */
    private PrisonQueryPageVO processPrisonData(Prison prison) {
        Integer prisonId = prison.getPrisonId();
        Integer prisonTypeId = prison.getPrisonTypeId();

        // 查询设备信息
        Integer strongState = getEquipmentState(prison.getEquipmentStrongId());
        Integer weakState = getEquipmentState(prison.getEquipmentWeakId());

        // 查询监狱类型信息
        PrisonType prisonType = prisonTypeService.getById(prisonTypeId);

        // 查询事件信息
        List<EventInfo> eventInfos = eventInfoService.list(new QueryWrapper<EventInfo>().eq("prison_id", prisonId));

        // 查询接口信息
        List<JackInfo> jackInfos = jackInfoService.list(new QueryWrapper<JackInfo>().eq("prison_id", prisonId));

        // 查询强电和弱电设备详情
        EquipmentInfo equipmentStrong = equipmentInfoService.getById(prison.getEquipmentStrongId());
        EquipmentInfo equipmentWeak = equipmentInfoService.getById(prison.getEquipmentWeakId());

        // 创建PrisonQueryPageVO对象
        PrisonQueryPageVO vo = new PrisonQueryPageVO();
        vo.setPrisonId(prisonId);
        vo.setPrisonName(prison.getPrisonName());
        vo.setUserInfoId(prison.getUserInfoId());
        vo.setPrisonDistrictId(prison.getPrisonDistrictId());
        vo.setEquipmentStrongId(prison.getEquipmentStrongId());
        vo.setEquipmentWeakId(prison.getEquipmentWeakId());
        vo.setPrisonTypeId(prisonTypeId);
        vo.setUnmWare(prison.getUnmWare());
        vo.setCreateTime(prison.getCreateTime());
        vo.setCreateBy(prison.getCreateBy());
        vo.setEventInfos(eventInfos);
        vo.setStrongState(strongState);
        vo.setWeakState(weakState);
        vo.setPrisonIds(null); // 可能需要具体值
        vo.setPrisonState(null); // 可能需要具体值
        vo.setEquipmentStrong(equipmentStrong);
        vo.setEquipmentWeak(equipmentWeak);
        vo.setJackInfos(jackInfos);
        vo.setPrisonType(prisonType);
        return vo;
    }

    /**
     * 获取设备状态。
     *
     * @param equipmentId 设备ID
     * @return 设备状态
     */
    private Integer getEquipmentState(Integer equipmentId) {
        if (equipmentId == null) {
            return null;
        }
        EquipmentInfo equipmentInfo = equipmentInfoService.getById(equipmentId);
        return equipmentInfo != null ? equipmentInfo.getState() : null;
    }

    /**
     * 构建分页结果。
     *
     * @param request 请求参数
     * @param resultList 处理后的监狱信息列表
     * @return 分页结果
     */
    private Page<PrisonQueryPageVO> buildPageResult(PrisonQueryRequest request, List<PrisonQueryPageVO> resultList) {
        Page<PrisonQueryPageVO> page = new Page<>(request.getCurrent(), request.getSize());
        page.setRecords(resultList);
        page.setTotal(prisonService.count());
        page.setSize(request.getSize());
        page.setCurrent(request.getCurrent());
        page.setPages((int) Math.ceil((double) prisonService.count() / request.getSize()));
        return page;
    }
}





